package gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import data.ChordTemplate;

@SuppressWarnings("serial")
public class ChordPanel extends JPanel implements ActionListener, ChangeListener {
	private Vector<JSlider> sliders;
	private JLabel lblNote1, lblNote2, lblNote3, lblNote4, lblNote5, lblNote6;
	private Vector<JLabel> noteValLabels;
	private JComboBox cmbChord;
	private JFileChooser fileChooser;
	private FileInputStream fis;
	private FileOutputStream fos;
	private ChordTemplate template;
	
	public ChordPanel(Color fgColor, Color bgColor, Font font, ChordTemplate template) {
		super(); // TODO: Choose LayoutManager, add buttons
		this.setBackground(bgColor);
		this.setBorder(BorderFactory.createLineBorder(fgColor));
		this.template = template;
		readTemplate();
		
		fileChooser = new JFileChooser();
		
		String[] items = {"OPEN", "SAVE"};
		cmbChord = new JComboBox(items);
		cmbChord.setForeground(fgColor);
		cmbChord.setBackground(bgColor);
		cmbChord.setFont(font);
		cmbChord.addActionListener(this);
		
		lblNote1 = new JLabel("Note 1: ");
		lblNote1.setForeground(fgColor);
		lblNote1.setFont(font);
		
		lblNote2 = new JLabel("Note 2: ");
		lblNote2.setForeground(fgColor);
		lblNote2.setFont(font);
		
		lblNote3 = new JLabel("Note 3: ");
		lblNote3.setForeground(fgColor);
		lblNote3.setFont(font);
		
		lblNote4 = new JLabel("Note 4: ");
		lblNote4.setForeground(fgColor);
		lblNote4.setFont(font);
		
		lblNote5 = new JLabel("Note 5: ");
		lblNote5.setForeground(fgColor);
		lblNote5.setFont(font);
		
		lblNote6 = new JLabel("Note 6: ");
		lblNote6.setForeground(fgColor);
		lblNote6.setFont(font);
		
		noteValLabels = new Vector<JLabel>();
		sliders = new Vector<JSlider>();
		for (int i = 0; i < 6; i++) {
			JSlider slider = new JSlider(new DefaultBoundedRangeModel(0, 0, 0, 36));
			slider.addChangeListener(this);
			slider.setForeground(fgColor);
			slider.setBackground(bgColor);
			sliders.add(slider);
			JLabel noteValLabel = new JLabel("0");
			noteValLabel.setForeground(fgColor);
			noteValLabel.setFont(font);
			noteValLabels.add(noteValLabel);
		}
		
		int[] notes = template.getNotes();
		for (int i = 0; i < notes.length; i++) {
			sliders.get(i).setValue(notes[i]);
			noteValLabels.get(i).setText("" + notes[i]);
			System.out.println("Slider" + i + ": " + notes[i]);
		}
		
		this.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		//c.gridheight = 6;
		//c.gridwidth = 3;
		
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 2;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(cmbChord, c);
		
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		c.weightx = 0.0;
		c.fill = GridBagConstraints.NONE;
		this.add(lblNote1, c);
		
		c.gridx = 1;
		c.gridy = 1;
		//c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 0.1;
		this.add(noteValLabels.get(0), c);
		
		c.gridx = 2;
		c.gridy = 1;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(0), c);
		
		c.gridx = 0;
		c.gridy = 2;
		c.weightx = 0.0;
		//c.weighty = 0.1;
		c.fill = 0;
		this.add(lblNote2, c);
		
		c.gridx = 1;
		c.gridy = 2;
		c.weightx = 0.1;
		//c.weighty = 0.1;
		//c.fill = GridBagConstraints.HORIZONTAL;
		this.add(noteValLabels.get(1), c);
		
		c.gridx = 2;
		c.gridy = 2;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		//c.weighty = 0.1;
		//c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(1), c);
		
		c.gridx = 0;
		c.gridy = 3;
		c.weightx = 0.0;
		c.fill = 0;
		this.add(lblNote3, c);
		
		c.gridx = 1;
		c.gridy = 3;
		c.weightx = 0.1;
		this.add(noteValLabels.get(2), c);
		
		c.gridx = 2;
		c.gridy = 3;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(2), c);
		
		c.gridx = 0;
		c.gridy = 4;
		c.weightx = 0.0;
		c.fill = 0;
		this.add(lblNote4, c);
		
		c.gridx = 1;
		c.gridy = 4;
		c.weightx = 0.1;
		this.add(noteValLabels.get(3), c);
		
		c.gridx = 2;
		c.gridy = 4;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(3), c);
		
		c.gridx = 0;
		c.gridy = 5;
		c.weightx = 0.0;
		c.fill = 0;
		this.add(lblNote5, c);
		
		c.gridx = 1;
		c.gridy = 5;
		c.weightx = 0.1;
		this.add(noteValLabels.get(4), c);
		
		c.gridx = 2;
		c.gridy = 5;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(4), c);
		
		c.gridx = 0;
		c.gridy = 6;
		c.weightx = 0.0;
		c.fill = 0;
		this.add(lblNote6, c);
		
		c.gridx = 1;
		c.gridy = 6;
		c.weightx = 0.1;
		this.add(noteValLabels.get(5), c);
		
		c.gridx = 2;
		c.gridy = 6;
		c.weightx = 0.5;
		c.fill = GridBagConstraints.HORIZONTAL;
		this.add(sliders.get(5), c);
	}
	
	private void readTemplate() {
		File file = new File(System.getProperty("user.dir") + System.getProperty("file.separator") + "chord");
		if (file.exists()) {
			try {
				fis = new FileInputStream(file);
				template.deserialize(fis);
			} 
			catch (FileNotFoundException fnfe) {
				fnfe.printStackTrace();
			}
		}
	}
	
	private void writeTemplate() {
		File file = new File(System.getProperty("user.dir") + System.getProperty("file.separator") + "chord");
		try {
			fos = new FileOutputStream(file);
			template.serialize(fos);
		} 
		catch (FileNotFoundException fnfe) {
			fnfe.printStackTrace();
		}
	}

	@Override
	public void actionPerformed(ActionEvent ae) {
		if (ae.getSource() == cmbChord) {
			String text = (String) cmbChord.getSelectedItem();
			if (text.equals("OPEN")) {
				int res = fileChooser.showOpenDialog(this);
				if (res == JFileChooser.APPROVE_OPTION) {
					try {
						fis = new FileInputStream(fileChooser.getSelectedFile());
						template.deserialize(fis);
						fis.close();
					} 
					catch (FileNotFoundException fnfe) {
						fnfe.printStackTrace();
					} 
					catch (IOException ioe) {
						ioe.printStackTrace();
					}
				}
			}
			else if (text.equals("SAVE")) {
				int res = fileChooser.showSaveDialog(this);
				if (res == JFileChooser.APPROVE_OPTION) {
					try {
						fos = new FileOutputStream(fileChooser.getSelectedFile());
						template.serialize(fos);
						fos.close();
					} 
					catch (FileNotFoundException fnfe) {
						fnfe.printStackTrace();
					} 
					catch (IOException ioe) {
						ioe.printStackTrace();
					}
				}
			}
		}
	}

	@Override
	public void stateChanged(ChangeEvent ce) {
		JSlider slider = (JSlider) ce.getSource();
		if (slider.getValueIsAdjusting()) {
			int val = slider.getValue();
			if (slider == sliders.get(0)) {
				noteValLabels.get(0).setText("" + val);
				template.setNote(0, val);
				writeTemplate();
			}
			else if (slider == sliders.get(1)) {
				noteValLabels.get(1).setText("" + val);
				template.setNote(1, val);
				writeTemplate();
			}
			else if (slider == sliders.get(2)) {
				noteValLabels.get(2).setText("" + val);
				template.setNote(2, slider.getValue());
				writeTemplate();
			}
			else if (slider == sliders.get(3)) {
				noteValLabels.get(3).setText("" + val);
				template.setNote(3, slider.getValue());
				writeTemplate();
			}
			else if (slider == sliders.get(4)) {
				noteValLabels.get(4).setText("" + val);
				template.setNote(4, slider.getValue());
				writeTemplate();
			}
			else if (slider == sliders.get(5)) {
				noteValLabels.get(5).setText("" + val);
				template.setNote(5, slider.getValue());
				writeTemplate();
			}
		}
	}
}